﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading;
using System.Diagnostics;

using KaixinRobot;

namespace KaixinHouse
{
    public class RunTime
    {
        private static int loopCounter = 0;
        //private static int callInterval = GlobalConfigHelper.config.RepeatTime;

        private static DateTime startTime = System.DateTime.Now.ToLocalTime();
        private static DateTime lastStartTime = System.DateTime.Now.ToLocalTime().AddDays(-1);
        private static DateTime endTime = System.DateTime.Now.ToLocalTime();
        private static DateTime schdNextRun = System.DateTime.Now.ToLocalTime();
        private static DateTime exptNextRun = System.DateTime.Now.ToLocalTime();

        private static string exptUserMail = null;
        private static string exptCompName = null;
        private static string currUserMail = null;
        private static string currCompName = null;

        private static bool isUrgentCall = false;

        public static void setCurEnv(string usermail, string compname)
        {
            //compname: move, slave, garden, work
            RunTime.currUserMail = usermail;
            RunTime.currCompName = compname;

            TraceLog.PrintLn("");
            TraceLog.PrintLn(">>>>>>  User={0}, Comp={1} <<<<<<", RunTime.currUserMail, RunTime.currCompName);
        }

        public static void exptRunAt(DateTime exp)
        {
            //多期待几分钟，因为可能有计时不准确的情况，同时可以避免冲突
            exp = exp.AddMinutes(2);

            //如果新设置的期待时间比原来的期待时间早，使用新设置的期待时间
            if ((exp != null) && (exp < RunTime.exptNextRun))
            {
                TraceLog.PrintLn("  * EXPECTED Next Run Time: {0} -> {1} !", RunTime.exptNextRun, exp);
                RunTime.exptNextRun = exp;
                RunTime.exptUserMail = RunTime.currUserMail;
                RunTime.exptCompName = RunTime.currCompName;
            }
        }

        //public static void setInterval(int itl)
        //{
        //    _RunTime.callInterval = itl;
        //}

        //检查程序是否需要再次被调用
        public static bool needRunAgain()
        {
            if (GlobalConfigHelper._default.RepeatTime == 0) return false;

            if (RunTime.schdNextRun <= System.DateTime.Now.ToLocalTime())
            {
                TraceLog.PrintLn("  * SCHEDULE Break! ");
                return true;
            }
            if (RunTime.exptNextRun <= System.DateTime.Now.ToLocalTime())
            {
                TraceLog.PrintLn("  * EXPECT Break! ");
                return true;
            }
            return false;
        }

        public static bool isANewDay()
        {
            if (startTime.Day != lastStartTime.Day)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private static void loopStart()
        {
            if (!RunTime.isUrgentCall)
            {
                TraceLog.PrintLn("  * LOOP - [{0}] starts ......", ++RunTime.loopCounter);

                //每次循环均重设 _RunTime.schdNextRun 为下次运行值
                RunTime.schdNextRun = System.DateTime.Now.ToLocalTime().AddMinutes(GlobalConfigHelper._default.RepeatTime);
                RunTime.exptNextRun = RunTime.schdNextRun;
                TraceLog.PrintLn("  * SCHEDULED next run set to: {0}!", RunTime.schdNextRun);

                //记录开始时间
                RunTime.startTime = System.DateTime.Now.ToLocalTime();
            }
            else
            {
                TraceLog.PrintLn("  * URGENT call starts ......");
            }
        }

        private static void loopEnd()
        {
            if (!RunTime.isUrgentCall)
            {
                //记录结束时间
                RunTime.endTime = System.DateTime.Now.ToLocalTime();

                //记录下程序开始运行时间，下次运行时，看看是不是新的一天
                RunTime.lastStartTime = RunTime.startTime;
            }
            else
            {
                //如果是紧急调用，清除紧急调用下次运行时间
                RunTime.isUrgentCall = false;
                RunTime.exptNextRun = System.DateTime.Now.ToLocalTime().AddDays(1);
            }
        }

        private static int getSleepMins()
        {
            TimeSpan inv;

            if (RunTime.exptNextRun < RunTime.schdNextRun)
            {
                RunTime.isUrgentCall = true;
                inv = RunTime.exptNextRun - System.DateTime.Now.ToLocalTime();
            }
            else
            {
                RunTime.isUrgentCall = false;
                inv = RunTime.schdNextRun - System.DateTime.Now.ToLocalTime();
            }

            return (int)inv.TotalMinutes;
        }

        private static void restSomeMins(int restTime)
        {
            while (restTime > 0)
            {
                TraceLog.PrintLn("  * Wait {0} mins to restart...", restTime--);
                Thread.Sleep(60 * 1000);
                if (RunTime.needRunAgain()) break;
            }
        }

        protected static void runonce()
        {

            string appName = Process.GetCurrentProcess().MainModule.FileName;
            string[] filelist = Directory.GetFiles(Path.GetDirectoryName(appName), "*.ini");
            Array.Sort(filelist);

            RunTime.loopStart();
            foreach (string filename in filelist)
            {
                try
                {
                    TraceLog.PrintLn("读取账号文件: " + filename);
                    if (filename.IndexOf("Slave") >= 0)
                    {
                        //处理Slave.ini
                        UserConfig._default = new UserConfig(filename);
                        Collection<UserIdentity> slaveList = UserConfig._default.slaveList;
                        UserConfig._default.slaveList = new Collection<UserIdentity>();

                        foreach (UserIdentity uid in slaveList)
                        {
                            UserConfig._default.master = uid;
                            UserConfig._default.sendList = new Collection<int>();
                            UserConfig._default.sendList.Add(TextParser.GetInteger(uid.userIdx));

                            uid.userIdx = null;

                            Account acc = new Account(uid);
                            acc.run();
                        }
                    }
                    else
                    {
                        Account acc = new Account(filename);
                        if (RunTime.isUrgentCall)
                        {
                            acc.run(RunTime.exptUserMail, RunTime.exptCompName);
                        }
                        else
                        {
                            acc.run();
                        }
                    }
                }
                catch (Exception e)
                {
                    TraceLog.Error(e.Message);
                }
            }
            RunTime.loopEnd();

            RunTime.restSomeMins(RunTime.getSleepMins());
        }

        public static void execute(string[] args)
        {

            if (args.Length >= 1)
            {
                //string[] test = { "-u", "seaza@sina.com", "-p", "iforgot", "-moveto", "12684807:5766" };
                //UserOperations.CallByParams(args);
                if (args[0].Equals("seedinfo"))
                {
                    UserIdentity tuid = new UserIdentity();
                    tuid.userMail = "cao_cao_bj@163.com";
                    tuid.userPass = "iforgot";

                    Account tacc = new Account(tuid);
                    Component.logon(tuid);
                    KXWeb.Garden.Get_Main();
                    //Garden.Seed.printAllSeedInfo(tacc.garden.verifyCode);
                }
            }
            else
            {
                while (true)
                {
                    RunTime.runonce();

                    //如果RepeatTime == 0， 只执行一次
                    if (GlobalConfigHelper._default.RepeatTime == 0) break;
                }
            }
        }
    }
}
